package gua

import (
	"fmt"
	"github.com/gorilla/websocket"
	log "github.com/sirupsen/logrus"
)

type Session struct {
	ID          int64           // 会话id
	Protocol    string          // 协议
	Mode        string          // 连接模式，备用字段,这个字段决定会话使用需要被Manager管理，以及断开时如何处理断开行为。
	WebSocket   *websocket.Conn // 和web的连接句柄
	GuacdTunnel *Tunnel         // 和guacd的连接通道
	Observer    *Manager        // observer 实例
}

type Manager struct {
	id       int64              // 会话id，只是为了方便使用面向对象的思维去操作session
	sessions map[int64]*Session // session map，key为session id，val 为session对象

	Add  chan *Session // 存储会话的chan
	Del  chan int64    // 删除会话的chan
	exit chan bool     // 判断某个会话是否还存在
}

func NewManager() {
	GuaSessionManager = &Manager{
		Add:      make(chan *Session),
		Del:      make(chan int64),
		sessions: map[int64]*Session{},
		exit:     make(chan bool, 1),
	}
	go GuaSessionManager.Start()
}

func NewObserver(id int64) *Manager {
	m := &Manager{
		id:       id,
		Add:      make(chan *Session),
		Del:      make(chan int64),
		sessions: map[int64]*Session{},
		exit:     make(chan bool, 1),
	}
	go m.Start()
	return m
}

func (m *Manager) Start() {
	defer fmt.Printf("Session Manager %v End\n", m.id)
	log.Debugf("Session Manager %v  Open\n", m.id)
	for {
		select {
		case s := <-m.Add:
			m.sessions[s.ID] = s
		case k := <-m.Del:
			if _, ok := m.sessions[k]; ok {
				ss := m.sessions[k]
				if ss.GuacdTunnel != nil {
					_ = ss.GuacdTunnel.Close()
				}
				if ss.WebSocket != nil {
					_ = ss.WebSocket.Close()
				}
				if ss.Observer != nil {
					ss.Observer.Close()
				}
				delete(m.sessions, k)
			}
		case <-m.exit:
			return
		}
	}
}

func (m *Manager) Close() {
	m.exit <- true
}

func (m Manager) GetById(id int64) *Session {
	return m.sessions[id]
}

func (m Manager) IsExist(id int64) bool {
	_, ok := m.sessions[id]
	return ok
}

func (m Manager) All() map[int64]*Session {
	return m.sessions
}
